#ifndef __UDSF_UDF_SWITCH_C_
#define __UDSF_UDF_SWITCH_C_

#include "udf_global.h"
#include "udf_def_auto.h"
/*
*   notice:
*   UDSF 同UDF编程：不可调用cstd-lib,只可调用"sdk_ifs_udk_cfg.h"、"sys_api.h"中列出的API函数。
*   UDSF文件内函数均需使用static修饰符，且UDF中以#include "UDSF.c"形式引用
*/

/*
note:
udf切换,本功能仅支持有片外flash应用方案，动态加载方式不支持udf切换

udf切换有两方面应用：
应用1: 代码分段在多个UDF中，以实现用户代码空间的扩充。
应用2: 切换flash内其它应用bin( 如UDF13实现高性能雷达，无目标时可切换至其它低功耗侦测UDF03应用,有目标时UDF03再切换回UDF13)
注：需注意: 应用2 切换会导致sUDF_global内全局变量值丢失。

udsf_udf_switch_extern 支持调用flash内其它工程编译的UDF03(!!!必须为UDF03,暂只支持UDF003) 外部工程调用udsf_udf_default切换回内置UDF
udsf_udf_switch        支持切换本工程编译的其它UDF (主要目的为UDF03/UDF07 调用UDF01/UDF09/UDF16 以实现代码空间的扩充)

注: udf03调用切换UDF01、UDF09、UDF16 可不开启crc
*/

#include "udsf_spiflash.c"
#include "udsf_crc.c"

#include "udsf_uart.c"
#include "udsf_memory_access.c"


static int udsf_udf_switch(uint8_t main_id,uint8_t switch_id,uint8_t crc_en ) __attribute__((unused));
static int udsf_udf_switch_extern(uint8_t crc_en,uint8_t ab_area_flag,uint32_t ab_area_size,uint8_t is_xip,uint8_t udt_src) __attribute__((unused));
static void udsf_udf_default(uint8_t is_xip,uint8_t udt_src) __attribute__((unused));


// 切换外部UDF      (内部UDF调用)   注: UDK-SYS 不支持调用该函数  // 外部独立应用应由UDK-USR-LITE开发编译
static int udsf_udf_switch_extern(uint8_t crc_en,uint8_t ab_area_flag,uint32_t ab_area_size,uint8_t is_xip,uint8_t udt_src){
	
	if( ab_area_flag ){
		ab_area_flag -= 1;
		if( ab_area_flag > 0 ){
			ab_area_flag = 1;
		}
	}
	
	uint32_t addr = UDF_END_ADDR + ab_area_flag*ab_area_size;
	
	udsf_memory_load2sram( addr,is_xip,udt_src,(uint8_t*)PARAM_BASEADDR,2048);
	
	paramFunc->udf03_addr.srcAddr = addr + 2048 + (paramFunc->udf03_addr.srcAddr - UDK_LITE_UDF_START_ADDR );
	if( crc_en ){
		uint16_t crc = udsf_get_crc((uint8_t *)paramFunc,paramFunc->crcLen);
		paramFunc->crcVal = crc;
	}
	paramDataPrep->switch_flag = 1;// 此为dataprep中预留区重定义，未计入crc校验长度
	return 0;
}

// 恢复内置默认UDF  (外部UDF调用)
static void udsf_udf_default(uint8_t is_xip,uint8_t udt_src){
	// load default udp_2k_param
	udsf_memory_load2sram(UDK_LITE_UDP_START_ADDR,is_xip,udt_src,(uint8_t*)PARAM_BASEADDR,2048);
	paramDataPrep->switch_flag = 1;  // 此为dataprep中预留区重定义，未计入crc校验长度
}

// 内部UDF间切换,成对使用,避免重复加载2K参数
// 用法：
// e.g. 如第一次UDF13内调用 udsf_udf_switch(13,1,x) // 由UDF13切换至UDF01 第二次调用 udsf_udf_switch(13,1,x) 由UDF01切换回UDF13
// e.g. 如第一次UDF03内调用 udsf_udf_switch(3,1,x)  // 由UDF03切换至UDF01 第二次调用 udsf_udf_switch(3,1,x) 由UDF01切换回UDF03
static int udsf_udf_switch(uint8_t main_id,uint8_t switch_id,uint8_t crc_en )
{
	int res = 0;
	
	PATCH_ADDR* udf_addr = &paramFunc->udf01_addr;	
	uint16_t * udf_len = &paramFunc->udf01_len;
	
	// main_id、switch_id指向的udf配置互换
	if( (main_id > 0 && main_id < 17) && (switch_id > 0 && switch_id < 17) ){
		
		PATCH_ADDR udfxx_addr_bkup = udf_addr[main_id-1];
		uint16_t udfxx_len_bkup = udf_len[main_id-1];
		
		udf_addr[main_id - 1] = udf_addr[switch_id-1];
		udf_len[main_id - 1]  = udf_len[switch_id-1];
		
		udf_addr[switch_id-1] = udfxx_addr_bkup;
		udf_len[switch_id-1]  = udfxx_len_bkup;
		
		paramDataPrep->switch_flag = 1;// 此为dataprep中预留区重定义，未计入crc校验长度
		if( crc_en ){
			uint16_t crc = udsf_get_crc((uint8_t *)paramFunc,paramFunc->crcLen);
			paramFunc->crcVal = crc;
		}
	}else{
		res = -1;
	}
	#ifdef UART_RECV_ENABLE  // 重设为工作模式

	#if APPLICATION_MODE == APPLICATION_MODE_ROM_START // xip模式 无需改回工作模式
	/* disable uart irq */
	NVIC->ICER[0] = (1 << ((uint32_t)(USCI1_IRQn) & 0x1F));
	USCI1->IMR=0xFFFFFFFF;	


	uint8_t * p_rom_global_workmode = p_work_mode;	
	/* set workmode->work mode */
	*p_rom_global_workmode = 1;
	#endif
	
	#endif
	return res;
}

#endif
